﻿using System.Collections.Generic;
using Godot.core.os;

namespace Godot.core.bind
{
    using SysMethodInfo = System.Reflection.MethodInfo;

    public partial class Directory : Reference
    {
        public Error open(string p_path) 
        {
	        Error err = Error.FAILED;
	        DirAccess alt = DirAccess.open(p_path,ref err);

	        if (null == alt)
		        return err; 
	        __d = alt;
	        return Error.OK;
        }

        public bool list_dir_begin() 
        {
	        if(null == __d) return false;
	        return __d.list_dir_begin();
        }

        public string get_next()
        {
	        if(null == __d) return "";
	        return __d.get_next();
        }

        public bool current_is_dir()
        {
	        if(null == __d) return false;
	        return __d.current_is_dir();
        }

        public bool list_dir_end()
        {
            if (null == __d) return false;
	        return __d.list_dir_end();
        }

        public int get_drive_count()
        {
	        if(null == __d) return 0;
	        return __d.get_drive_count();
        }

        public string get_drive(int p_drive)
        {
	        if(null == __d) return "";
	        return __d.get_drive(p_drive);
        }

        public Error change_dir(string p_dir)
        {
	        if(null == __d) return Error.ERR_UNCONFIGURED;
	        return __d.change_dir(p_dir);
        }

        public string get_current_dir() 
        {
	        if(null == __d) return "";
	        return __d.get_current_dir();
        }

        public Error make_dir(string p_dir)
        {
	        if(null == __d) return Error.ERR_UNCONFIGURED;
	        return __d.make_dir(p_dir);
        }

        public Error make_dir_recursive(string p_dir)
        {
	        if(null == __d) return Error.ERR_UNCONFIGURED;
	        return __d.make_dir_recursive(p_dir);
        }

        public bool file_exists(string p_file)
        {
	        if(null == __d) return false;
	        return __d.file_exists(p_file);
        }

        public int get_space_left()
        {
	        if(null == __d) return 0;
	        return (int)__d.get_space_left();
        }

        public Error copy(string p_from, string p_to)
        {
	        if(null == __d) return Error.ERR_UNCONFIGURED;
	        return __d.copy(p_from, p_to);
        }

        public Error rename(string p_from, string p_to)
        {
	        if(null == __d) return Error.ERR_UNCONFIGURED;
	        return __d.rename(p_from,p_to);
        }

        public Error remove(string p_name)
        {
	        if(null == __d) return Error.ERR_UNCONFIGURED;
	        return __d.remove(p_name);
        }

        protected static new void _bind_methods()
        {
            ObjectTypeDB.bind_method(_MD("open:Error","path"),typeof(Directory).GetMethod("open", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("list_dir_begin"),typeof(Directory).GetMethod("list_dir_begin", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("get_next"),typeof(Directory).GetMethod("get_next", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("current_is_dir"),typeof(Directory).GetMethod("current_is_dir", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("list_dir_end"),typeof(Directory).GetMethod("list_dir_end", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("get_drive_count"),typeof(Directory).GetMethod("get_drive_count", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("get_drive","idx"),typeof(Directory).GetMethod("get_drive", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("change_dir:Error","todir"),typeof(Directory).GetMethod("change_dir", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("get_current_dir"),typeof(Directory).GetMethod("get_current_dir", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("make_dir:Error","name"),typeof(Directory).GetMethod("make_dir", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("make_dir_recursive:Error","name"),typeof(Directory).GetMethod("make_dir_recursive", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("file_exists","name"),typeof(Directory).GetMethod("file_exists", Misc.BindingFlags_Greedy));
        //	ObjectTypeDB.bind_method(_MD("get_modified_time","file"),typeof(Directory).GetMethod("get_modified_time", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("get_space_left"),typeof(Directory).GetMethod("get_space_left", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("copy:Error","from","to"),typeof(Directory).GetMethod("copy", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("rename:Error","from","to"),typeof(Directory).GetMethod("rename", Misc.BindingFlags_Greedy));
	        ObjectTypeDB.bind_method(_MD("remove:Error","file"),typeof(Directory).GetMethod("remove", Misc.BindingFlags_Greedy));
        }

        private DirAccess __d;
    }

    public partial class Directory
    {
        #region	OBJ_TYPE(Directory, Reference)
        public override string get_type() { return "Directory"; }

        public override string get_save_type() { return get_type(); } //type stored when saving

        public override StringName get_type_name() { return (StringName)get_type_static(); }

        public override bool is_type(string p_type) { return (p_type == "Directory") ? true : base.is_type(p_type); }

        protected override void _initialize_typev() { initialize_type(); }

        protected override bool _setv(StringName p_name, Variant p_property)
        {
            if (base._setv(p_name, p_property))
                return true;

            if (typeof(Directory).GetMethod("_set", Misc.BindingFlags_Greedy) != typeof(Reference).GetMethod("_set", Misc.BindingFlags_Greedy))
            {
                return _set(p_name, p_property);
            }

            return false;
        }

        protected override bool _getv(StringName p_name, ref Variant r_property)
        {
            if (typeof(Directory).GetMethod("_get", Misc.BindingFlags_Greedy) != typeof(Reference).GetMethod("_get", Misc.BindingFlags_Greedy))
            {
                if (_get(p_name, ref r_property))
                    return true;
            }

            return base._getv(p_name, ref r_property);
        }

        protected override void _get_property_listv(ref List<PropertyInfo> p_list, bool p_reversed)
        {
            if (!p_reversed)
            {
                base._get_property_listv(ref p_list, p_reversed);
            }

            p_list.Add(new PropertyInfo(Variant.Type.NIL, get_type_static(), PropertyHint.PROPERTY_HINT_NONE, "", (int)PropertyUsageFlags.PROPERTY_USAGE_CATEGORY));

            if (!_is_gpl_reversed())
                ObjectTypeDB.get_property_list("Directory", ref p_list, true);

            if (typeof(Directory).GetMethod("_get_property_list", Misc.BindingFlags_Greedy) != typeof(Reference).GetMethod("_get_property_list", Misc.BindingFlags_Greedy))
            {
                _get_property_list(ref p_list);
            }

            if (_is_gpl_reversed())
                ObjectTypeDB.get_property_list("Directory", ref p_list, true);

            if (p_reversed)
            {
                base._get_property_listv(ref p_list, p_reversed);
            }
        }

        protected override void _notificationv(int p_notification, bool p_reversed)
        {
            if (!p_reversed)
                base._notificationv(p_notification, p_reversed);

            if (typeof(Directory).GetMethod("_notification", Misc.BindingFlags_Greedy) != typeof(Reference).GetMethod("_notification", Misc.BindingFlags_Greedy))
            {
                _notification(p_notification);
            }

            if (p_reversed)
                base._notificationv(p_notification, p_reversed);
        }

        public static new string get_type_static() { return "Directory"; }

        public static new string get_parent_type_static() { return Reference.get_type_static(); }

        public static new void get_inheritance_list_static(ref List<string> r_inheritance_list)
        {
            Reference.get_inheritance_list_static(ref r_inheritance_list);
            r_inheritance_list.Add(get_type_static());
        }

        public static new string get_category_static()
        {
            string category = Reference.get_category_static();
            if (typeof(Directory).GetMethod("_get_category", Misc.BindingFlags_Greedy) != typeof(Reference).GetMethod("_get_category", Misc.BindingFlags_Greedy))
            {
                if (category != "")
                    category += "/";
                category += _get_category();
            }
            return category;
        }

        public static new string inherits_static() { return "Reference"; }

        public static new void get_valid_parents_static(ref List<string> p_parents)
        {
            if (typeof(Directory).GetMethod("_get_valid_parents_static", Misc.BindingFlags_Greedy) != typeof(Reference).GetMethod("_get_valid_parents_static", Misc.BindingFlags_Greedy))
            {
                Directory._get_valid_parents_static(ref p_parents);
            }

            Reference.get_valid_parents_static(ref p_parents);
        }

        public static new void initialize_type()
        {
            if (__initialized)
                return;
            Reference.initialize_type();
            ObjectTypeDB._add_type<Directory>();

            SysMethodInfo cls_bind = typeof(Directory).GetMethod("_bind_methods", Misc.BindingFlags_Greedy);
            SysMethodInfo par_bind = typeof(Reference).GetMethod("_bind_methods", Misc.BindingFlags_Greedy);
            if (cls_bind != par_bind)
                cls_bind.Invoke(null, null);
            __initialized = true;
        }

        private static bool __initialized = false;
        #endregion
    }
}
